package com.into.common.csv.engine;

import com.into.common.csv.CSVField;
import com.into.common.csv.CSVFieldsDefiner;

/**
 * Chain of responsibility that handles {@link CSVFieldsDefiner}
 * 
 * You can use this class to handle mutliple content type csv files by creating
 * a separate {@link CSVFieldsDefiner} for each type and implementing
 * {@link #handles(String[])} to take the responsibility of handling the object
 * or delegating it to the chain.
 * 
 * @author Zied Hamdi
 * 
 */
public abstract class CSVFieldsDefinerHandler implements CSVFieldsDefiner {

	protected CSVFieldsDefiner next;

	public CSVFieldsDefinerHandler() {
		this(null);
	}

	public CSVFieldsDefinerHandler(CSVFieldsDefiner next) {
		this.next = next;
	}

	public CSVFieldsDefiner getNext() {
		return next;
	}

	public void setNext(CSVFieldsDefiner next) {
		this.next = next;
	}

	public final Object createInstance(String[] values) {
		if (handles(values))
			return createConcreteInstance(values);

		return next == null ? null : next.createInstance(values);
	}

	@Override
	public final CSVField<?>[] getCSVFields(String[] values) {
		if (handles(values))
			return getConcreteCSVFields(values);
		return next == null ? null : next.getCSVFields(values);
	}

	@Override
	public final CSVField<?>[] getCSVFields(Object value) {
		if (handles(value))
			return getConcreteCSVFields(value);
		return next == null ? null : next.getCSVFields(value);
	}

	protected abstract CSVField<?>[] getConcreteCSVFields(String[] values);

	protected abstract CSVField<?>[] getConcreteCSVFields(Object value);

	protected abstract Object createConcreteInstance(String[] values);

	protected abstract boolean handles(String[] values);

	protected abstract boolean handles(Object value);

}
